<template>
    <div ref="container" class="container">
        <!-- <div ref="container" class="container"></div> -->
    </div>
</template>

<script>
import { scaleData } from '@/utils/common';
import location from '@/assets/svg/location.svg';

/* eslint-disable no-undef */
const LEVEL_PROVINCE = 1;
export default {
    name: 'Map',

    components: {},

    props: {
        // 当前选中的画画方式
        currentSelectType: {
            type: Object,
            default: function () {
                return {};
            },
        },
        // 所有楼盘点位数据
        buildings: {
            type: Array,
            required: true,
        },
        // 传入的半径
        radius: {
            type: Number,
            default: 0,
        },
        // 传入的城市名
        cityName: {
            type: String,
            default: '',
        },
    },

    data: () => ({
        // dialogVisible: false,
        drawType: '',
        map: null,
        points: [],
        pointsOverlayObj: {
            // 记录已选和未选海量点的对象 用于重画
            selectedOverlay: null,
            unSelectedOverlay: null,
            isShow: false,
        },
        pointsOptions: {
            0: {
                shape: BMAP_POINT_SHAPE_CIRCLE,
                color: '#E60044',
            },
            1: {
                shape: BMAP_POINT_SHAPE_CIRCLE,
                color: '#278E2F',
            },
        },
        selectedBuildings: [], // 当前选中楼盘
        drawingManager: null,
        heatmapOverlay: null,
        pathArr: {},
        indexArr: [],
        labelsArr: [], // 存储label覆盖物的变量 用于清楚label
        styleOptions: {
            strokeColor: '#E60044', // 边线颜色。
            fillColor: '#E60044', // 填充颜色。当参数为空时，圆形将没有填充效果。
            strokeWeight: 2, // 边线的宽度，以像素为单位。
            strokeOpacity: 1, // 边线透明度，取值范围0 - 1。
            fillOpacity: 0.15, // 填充的透明度，取值范围0 - 1。
            strokeStyle: 'solid', // 边线的样式，solid或dashed。
        },
        countryCenter: {
            // 全国坐标
            lng: 114.113109,
            lat: 37.550339,
        },
    }),

    watch: {
        buildings(val, old) {
            // if (val.length > 0) {
            if (!Array.isArray(this.points) && val.length) {
                Object.keys(this.points).forEach((key) => {
                    const temp = val.find(({ id }) => id === key);
                    if (temp) {
                        this.points[key].selected = temp.selected;
                    }
                });
            } else {
                this.points = { ...this.normalizePointsAll(val) };
            }

            // if (Object.keys(this.points).length) {
            this.pointsOverlayObj.isShow = true;
            this.jugDraw();
            // }
            // }
        },

        selectedBuildings(val) {
            this.$emit('returnSelectedBuildings', val);
        },
        cityName(val) {
            if (val) {
                setTimeout(() => {
                    this.setCenterWidthCityName(val);
                }, 100);
            }
        },
    },

    mounted() {
        this.updateMap();
    },

    methods: {
        panTo(location) {
            this.map.panTo(new BMap.Point(location.lng, location.lat));
        },

        updateMap() {
            const cityName = this.cityName || '北京市';
            let map = new BMap.Map(this.$refs.container, {
                enableMapClick: false, // 禁止默认窗口
            });
            this.map = map;
            // this.setCity({ name: this.cityName })
            map.enableScrollWheelZoom(); // 开启鼠标滚轮缩放
            this.mapBindEvent();
            this.setCenterWidthCityName(cityName);
        },

        setCity(city) {
            // 设置中心城市
            this.map.centerAndZoom(city.name, 12);
        },
        setCenterWidthCityName(cityName) {
            // 设置中心城市
            this.map.centerAndZoom(cityName, 11);
        },
        setCenter(data, level) {
            if (Number(level) === LEVEL_PROVINCE) {
                // 全国
                let point = new BMap.Point(this.countryCenter.lng, this.countryCenter.lat);
                this.map.centerAndZoom(point, 6);
            } else {
                this.setCity(data);
            }
        },
        location() {
            return new Promise((resolve) => {
                let myCity = new BMap.LocalCity();
                myCity.get((result) => {
                    resolve(result);
                });
            });
        },
        normalizePointsAll(arr) {
            let obj = {};
            arr.forEach((item) => {
                obj[item.id] = {
                    point: new BMap.Point(parseFloat(item.positionLng), parseFloat(item.positionLat)),
                    ...item,
                    lat: parseFloat(item.positionLat),
                    lng: parseFloat(item.positionLng),
                    type: -1,
                    choose: item.choose,
                };
            });
            return obj;
        },
        jugDraw() {
            this.drawDevicePoints();
            // if (!this.pointsOverlayObj.isShow) {
            //   this.drawMarkers()
            // }
        },
        //
        // 根据预算随机得到已选的楼盘数据
        //
        drawDevicePoints() {
            let selectP = [],
                unSelectP = [],
                selectedBuildings = [];
            Object.values(this.points).forEach((item) => {
                if (item.selected === 0) {
                    unSelectP.push(item);
                } else {
                    selectP.push(item);
                }
                if (item.type > -1) {
                    selectedBuildings.push(item);
                }
            });
            this.drawBg(selectP, unSelectP, selectedBuildings);
        },

        //
        // 传已选及未选的点画背景点
        //
        //
        // 画背景点
        //
        drawBg(selectP, unSelectP, selectedBuildings) {
            this.selectedBuildings = selectedBuildings;
            this.drawPoints(selectP, unSelectP);
        },

        // 根据传入的以选中和未选中楼盘重新画数据
        drawPoints(selectP, unSelectP) {
            this.setDevicePoints(selectP, 0);
            this.setDevicePoints(unSelectP, 1);
        },
        //
        // 画背景点方法 0：已选 1：未选
        //
        setDevicePoints(points, type) {
            let str = type === 0 ? 'selected' : 'unSelected';
            let overlay = `${str}Overlay`;
            if (!this.pointsOverlayObj[overlay]) {
                let pointsOverlay = new BMap.PointCollection(points, this.pointsOptions[type]);
                this.pointsOverlayObj[overlay] = pointsOverlay;
                this.map.addOverlay(pointsOverlay);
                // pointsOverlay.disableMassClear()
                pointsOverlay.addEventListener('click', this.pointEvent);
                // pointsOverlay.addEventListener('mouseout', this.pointEventOut);
                // pointsOverlay.addEventListener('click', this.pointEventClick);
                // setTimeout(() => {
                //   this.setPaneIndex()
                // }, 0)
            } else if (points.length === 0) {
                // this.pointsOverlayObj[overlay].removeEventListener('mouseover',  this.pointEvent);
                // this.pointsOverlayObj[overlay].removeEventListener('mouseout',  this.pointEventOut);
                // this.pointsOverlayObj[overlay].removeEventListener('click',  this.pointEventClick);
                this.pointsOverlayObj[overlay].clear();
            } else {
                this.pointsOverlayObj[overlay].clear();
                this.pointsOverlayObj[overlay].setPoints(points);
            }
        },
        // 为海量点添加点击事件
        pointEvent(event) {
            if (this.currentSelectType === null || this.currentSelectType.type === 'hander') {
                this.removeLabels();
                this.addLabel(event.point);
            }
        },
        removeLabels() {
            let dom = document.getElementsByClassName('BMapLib_bubble_close')[0];
            if (dom) {
                dom.click();
            }
        },
        // 添加lable
        addLabel(point) {
            let content = `
          <div style="display:flex;">
            <img src="${point.skupic}" style="width:80px;height:80px;">
            <div style="margin-left:10px;flex: 1;display:flex; display: flex;
    flex-direction: column;
    justify-content: space-between;">
              <div style="color:#252525;font-weight:500;font-size: 14px;">${point.name}</div>
              <div style="color:#666;">
                <div style="padding: 4px 6px;display:inline-block;margin-right:10px;font-size:12px;background: #F5F5F5;border: 0 solid #F5F5F5;border-radius: 2px;">${point.areaName}</div>
                <div style="padding: 4px 6px;display:inline-block;font-size:12px;background: #F5F5F5;border: 0 solid #F5F5F5;border-radius: 2px;">${point.typeName}</div>
              </div>


                <div class="font-number" style="color:#999;"><img style="display:inline-block !important;width:10px;margin-right:4px;" src=${location}>${point.address}</div>


            </div>
          </div>
        `;

            let searchInfoWindow3 = new BMapLib.SearchInfoWindow(this.map, content, {
                title: '楼盘详情', // 标题
                width: 340, // 宽度
                height: 160, // 高度
                panel: 'panel', // 检索结果面板
                enableAutoPan: true, // 自动平移
                enableSendToPhone: false, // 右上角手机图标
                searchTypes: [],
            });
            searchInfoWindow3.open(new BMap.Point(point.lng, point.lat));
            setTimeout(() => {
                document.querySelector('#detail').addEventListener('click', (e) => {
                    this.$emit('showPremisesId', document.querySelector('#detail').getAttribute('data-premisesId'));
                });
            }, 100);
        },
        //
        // 得出在当前操作路径区域内的点
        //
        isInArea(path) {
            let points = this.points;
            if (path.type === 'polyline') {
                this.filterProjectByPolyline(this.points, path.overlay, path.radius, path.index);
            } else if (path.type === 'polygon' || path.type === 'rectangle') {
                for (let key in points) {
                    if (this.getPointChangeAble(points[key], path.index)) {
                        let b = points[key].point;
                        if (BMapLib.GeoUtils.isPointInPolygon(b, path.overlay)) {
                            points[key].type = path.index;
                        } else {
                            points[key].type = -2;
                        }
                    }
                }
            } else if (path.type === 'circle') {
                for (let key in points) {
                    let b = points[key].point;
                    if (this.getPointChangeAble(points[key], path.index)) {
                        if (BMapLib.GeoUtils.isPointInCircle(b, path.overlay)) {
                            points[key].type = path.index;
                        } else {
                            points[key].type = -2;
                        }
                    }
                }
            }
        },

        //
        // 折线判断点位是否在区域内
        //
        filterProjectByPolyline(points, overlay, radius, index) {
            let polyline = overlay.getPath();
            let len = polyline.length;

            // 重置折线的点type为-2为了之后改变type值不会出错
            this.changePathPointType(index, -2);

            // 圆形计算
            for (let i in polyline) {
                let circle = new BMap.Circle(polyline[i], radius, this.styleOptions);
                for (let key in points) {
                    if (this.judgePointType(points[key]) && points[key].type < 0) {
                        let b = points[key].point;
                        if (BMapLib.GeoUtils.isPointInCircle(b, circle)) {
                            points[key].type = index;
                        } else {
                            points[key].type = -2;
                        }
                    }
                }
            }
            // 未选 多边形计算
            let polygons = [];
            for (let k in polyline) {
                let kk = parseInt(k, 10);
                if (kk >= len - 1) {
                    break;
                }
                let lat1 = polyline[kk].lat;
                let lng1 = polyline[kk].lng;
                let lat2 = polyline[parseInt(kk + 1, 10)].lat;
                let lng2 = polyline[parseInt(kk + 1, 10)].lng;
                // 得到折线上所有多边形集合
                polygons.push(this.getFourP(lat1, lng1, lat2, lng2, radius));
            }
            for (let j in polygons) {
                for (let key in points) {
                    if (this.judgePointType(points[key]) && points[key].type < 0) {
                        let b = points[key].point;
                        if (BMapLib.GeoUtils.isPointInPolygon(b, polygons[j])) {
                            points[key].type = index;
                        } else {
                            points[key].type = -2;
                        }
                    }
                }
            }
        },

        getFourP(lan1, lon1, lan2, lon2, len) {
            // 返回一个计算的多边形
            let a = this.getDian(lan1, lon1, lan2, lon2, len);
            let b = this.getDian(lan1, lon1, lan2, lon2, -len);
            let c = this.getDian(lan2, lon2, lan1, lon1, len);
            let d = this.getDian(lan2, lon2, lan1, lon1, -len);
            let lists = [];
            for (let n of [a, b, c, d, a]) {
                lists.push(new BMap.Point(n.lon, n.lan));
            }
            let polygon = new BMap.Polygon(lists);
            return polygon;
        },

        getDian(lan1, lon1, lan2, lon2, len) {
            // 计算矩形四个点经纬度坐标
            let point1 = new BMap.Point(lon1, lan1);
            let point2 = new BMap.Point(lon2, lan2);
            let AB = BMapLib.GeoUtils.getDistance(point1, point2);
            let AC = Math.sqrt(AB * AB + len * len);
            let sina = (lan2 - lan1) / AB;
            let cosa = (lon2 - lon1) / AB;
            let sinb = len / AC;
            let cosb = AB / AC;
            let sinA = sina * cosb + sinb * cosa;
            let cosA = cosa * cosb - sina * sinb;
            let Ch = sinA * AC;
            let Cw = cosA * AC;
            let lon3 = lon1 + Cw;
            let lan3 = lan1 + Ch;
            return { lan: lan3, lon: lon3 };
        },

        getPointChangeAble(point, index) {
            if (this.judgePointType(point) && point.type < 0 || point.type === index) {
                return true;
            }
            return false;
        },

        // 根据type判断当前点是否可以被改变
        judgePointType(item) {
            if (item.type !== -3 && item.type !== 100) {
                return true;
            }
            return false;
        },

        // 将背景点中type为x的设置成y 如果x为null则将所有可修改背景点type替换成y
        changePathPointType(x, y) {
            if (x === null) {
                Object.values(this.points).forEach((item) => {
                    if (this.judgePointType(item)) {
                        item.type = y;
                    }
                });
            } else {
                Object.values(this.points).forEach((item) => {
                    if (item.type === x) {
                        item.type = y;
                    }
                });
            }
        },
        mapBindEvent() {
            this.map.addEventListener('dragend', this.drawMarkersByVisual); // 拖拽
            this.map.addEventListener('zoomend', this.mapZoomEnd); // 放大
            this.map.addEventListener('click', this.mapLeftClick); // 点击
            this.map.addEventListener('mousemove', this.mapMouseMove); // 鼠标移入
            this.map.addEventListener('rightclick', this.mapRightClick); // 右键点击
            this.map.addEventListener('load', this.mapLoad); // 加载
            // this.map.addEventListener('click', this.mapRightClick)
            // this.map.addEventListener('tilesloaded', this.tilesloaded)
        },

        removeEvent() {
            this.map.removeEventListener('dragend', this.drawMarkersByVisual);
            this.map.removeEventListener('click', this.mapLeftClick);
            this.map.removeEventListener('zoomend', this.mapZoomEnd);
            this.map.removeEventListener('mousemove', this.mapMouseMove);
            this.map.removeEventListener('rightclick', this.mapRightClick);
            this.map.removeEventListener('load', this.mapLoad);
        },

        // 缩放时的回调
        mapZoomEnd() {
            // this.drawMarkersByVisual()
            this.zoomChangeAllPath();
        },

        zoomChangeAllPath() {
            for (let key in this.pathArr) {
                if (this.pathArr[key].type === 'polyline') {
                    // 只有折线需要在改变zoom时变半径，圆和多边形都是自动变的
                    this.zoomSinglePathChange(this.pathArr[key]);
                }
            }
        },

        zoomSinglePathChange(path) {
            if (path.type === 'polygon') {
                return;
            }
            let radius = this.realDistanceTranPixels(path.radius);
            if (path.type === 'polyline') {
                path.overlay.setStrokeWeight(2 * radius);
            } else if (path.type === 'circle') {
                path.overlay.setRadius(path.radius);
            }
        },

        // 列表操作以后,更新点位,重新渲染右边列表
        updateTableList() {
            for (let key in this.pathArr) {
                this.getPopUpData(this.pathArr[key]);
            }
        },

        // 清空pathArr数据 并且清楚覆盖物
        clearPathArr(type = 0) {
            for (let key in this.pathArr) {
                this.map.removeOverlay(this.pathArr[key].overlay);
                if (this.pathArr[key].anotherOverlay) {
                    this.map.removeOverlay(this.pathArr[key].anotherOverlay);
                }
            }
            this.pathArr = {};
            this.indexArr = [];
            if (type === 0) {
                this.changePathPointType(null, -1);
                this.jugDraw();
            }
            this.removeLabels();
            // this.$emit('drawCancle')
        },

        // 返回上一步
        returnAfter() {
            if (this.indexArr.length > 0) {
                this.map.removeOverlay(this.pathArr[this.indexArr.length - 1].overlay);
                if (this.pathArr[this.indexArr.length - 1].anotherOverlay) {
                    this.map.removeOverlay(this.pathArr[this.indexArr.length - 1].anotherOverlay);
                }
                this.changePathPointType(this.indexArr.length - 1, -1);
                delete this.pathArr[this.indexArr.length - 1];
                this.indexArr.pop();
                this.jugDraw();
            }
            // this.$emit('drawCancle')
        },

        mapLoad() {
            // this.map.getPanes().mapPane.innerHTML = ''

            // this.initPointsOverlay()
            this.initMouse();
            let opts = {
                anchor: BMAP_ANCHOR_BOTTOM_LEFT,
                offset: new BMap.Size(36, 100),
                type: BMAP_NAVIGATION_CONTROL_ZOOM,
            };
            this.map.addControl(new BMap.NavigationControl(opts));
            this.map.addControl(new BMap.ScaleControl());
            // this.setSvgIndex()
            // setTimeout(() => {
            // this.setPaneIndex()
            // }, 0)
            this.$emit('mapLoad');
        },

        initMouse() {
            // 实例化鼠标绘制工具
            let drawingManager = new BMapLib.DrawingManager(this.map, {
                isOpen: false, // 是否开启绘制模式
                enableDrawingTool: true, // 是否显示工具栏
                drawingToolOptions: {
                    anchor: BMAP_ANCHOR_TOP_RIGHT, // 位置
                    offset: new BMap.Size(5, 5), // 偏离值
                    drawingModes: [
                        BMAP_DRAWING_CIRCLE,
                        BMAP_DRAWING_RECTANGLE,
                        BMAP_DRAWING_POLYLINE,
                        BMAP_DRAWING_POLYGON,
                    ],
                },
                circleOptions: this.styleOptions, // 画圆
                polylineOptions: this.styleOptions, // 线的样式
                polygonOptions: this.styleOptions, // 多边形的样式
                rectangleOptions: this.styleOptions, // 画矩形
            });
            this.drawingManager = drawingManager;
            this.drawComplete(drawingManager);
        },
        // 折线和多边形画线完成回调函数
        drawComplete(drawingManager) {
            drawingManager.addEventListener('overlaycomplete', (e) => {
                if (!this.drawErrorTip(e)) {
                    return;
                }
                let location = this.map.pixelToPoint(e.currentTarget._mask._draggingMovePixel);
                let path = {
                    type: e.drawingMode,
                    overlay: e.overlay,
                    location: location, // 结束绘制时鼠标的经纬度位置用于显示弹窗位置
                    index: this.indexArr.length, // 即将是pathArr的第几个元素
                    radius: this.radius, // 这里只有折线会用这个属性，折线的直径就是defaultRadius的两倍
                    points: e.overlay.getPath(),
                };
                if (e.drawingMode === 'polyline') {
                    this.drawpolylineBg(path, e.overlay);
                    this.$emit('drawCancle');
                } else if (e.drawingMode === 'polygon') {
                    this.getPopUpData(path);
                    this.$emit('drawCancle');
                } else {
                    this.getPopUpData(path);
                    // this.overlayBindEvent(path)
                }

                this.setSvgIndex();
            });
        },

        //
        // 画折现背景层
        //
        drawpolylineBg(path, overlay) {
            let radius = this.realDistanceTranPixels(path.radius);
            let polyline = new BMap.Polyline(path.overlay.getPath(), {
                strokeColor: '#E60044', // 边线颜色。
                // strokeWeight: 2 * radius,       //边线的宽度，以像素为单位。
                strokeOpacity: 0.15, // 边线透明度，取值范围0 - 1。
                strokeStyle: 'solid', // 边线的样式，solid或dashed。
            });
            polyline.setStrokeWeight(2 * radius);
            let ol = { ...path, overlay: polyline, anotherOverlay: overlay };
            this.map.addOverlay(polyline);
            // this.overlayBindEvent(ol)
            this.getPopUpData(ol);
        },

        //
        // 整理得到弹窗所需数据
        //
        getPopUpData(path) {
            this.isInArea(path);
            this.pathArr = { [path.index]: path, ...this.pathArr };
            this.indexArr[path.index] = path.index; // 记录所有画过路径的index数组
            this.jugDraw();
            this.activePath = this.pathArr[path.index];
        },

        realDistanceTranPixels(distance) {
            let zoom = this.map.getZoom();
            let pixDistance;
            for (let i = 0; i < scaleData.length; i++) {
                if (scaleData[i].zoom === zoom) {
                    let scale = scaleData[i].Pixels / scaleData[i].length;
                    pixDistance = scale * distance;
                }
            }
            return pixDistance;
        },

        // 当前选点不规范时提示并取消选点
        drawErrorTip(e) {
            let p = e.overlay.getPath();
            if (p.length === 1 || this.isAllEqual(p)) {
                this.$message.error('当前选点的位置太接近，无法进行地图选点！');
                this.$emit('drawCancle');
                return false;
            }
            if (e.drawingMode === 'polygon' && p.length === 2) {
                this.$message.error('多边形至少进行三次选点才能形成有效选点区域！');
                this.$emit('drawCancle');
                this.map.removeOverlay(e.overlay);
                return false;
            }
            return true;
        },

        setSvgIndex() {
            setTimeout(() => {
                if (this.map.getPanes().mapPane.getElementsByTagName('svg').length) {
                    this.map.getPanes().mapPane.getElementsByTagName('svg')[0].style.zIndex = 1000;
                }
            });
        },

        // 判断数组中数据是够全等
        isAllEqual(array) {
            if (array.length > 0) {
                return array.every(function (value) {
                    return value.equals(array[0]);
                });
            }
            return true;
        },

        mapLeftClick(event) {
            if (this.currentSelectType && this.currentSelectType.type === 'handCircle') {
                // 地址逆解析
                new BMap.Geocoder().getLocation(event.point, (rs) => {
                    this.drawCircle(event.point, rs.address);
                });
            }
            this.$emit('hidePopup');
        },

        // 画圆的函数
        drawCircle(point, info) {
            let newPoint = new BMap.Point(point.lng, point.lat);
            // let marker = this.addMarkerIcon(point)
            let circle = new BMap.Circle(newPoint, this.radius, this.styleOptions);
            this.map.addOverlay(circle);
            let path = {
                type: 'circle',
                overlay: circle,
                // anotherOverlay: marker,
                location: newPoint, // 结束绘制时鼠标的经纬度位置用于显示弹窗位置
                isShow: true,
                index: this.indexArr.length,
                radius: this.radius,
                points: circle.getCenter(),
            };

            // if (this.$tools.type(info) === 'object') {
            //   path.name = info.title
            //   path.address = info.address
            // } else {
            //   path.address = info
            // }
            // this.removeLabels()
            this.getPopUpData(path);
            // this.overlayBindEvent(path)
            // this.setSvgIndex()
        },

        //
        // 因为折线和多边形是依赖于开源库DrawingManager，
        // 但是元素不能显示，这里手动触发画折线和多边形方法
        //
        triggerDraw(type) {
            let dom = document.getElementsByClassName(`BMapLib_${type}`)[0];
            if (dom) {
                dom.click();
            }
        },

        //
        // 关闭DrawingManager画线方法 需要在绘画类型切换成圆形时调用
        //
        closeDrawingManager() {
            if (this.drawingManager) {
                this.drawingManager.close();
            }
        },
    },
};
</script>

<style lang="scss" scoped>
.container {
    width: 100%;
    height: 100%;
}
::v-deep .BMapLib_SearchInfoWindow {
    border: none;
    padding: 20px;
    font-family: inherit;
    width: 350px;
    box-sizing: border-box;
    img:last-child {
        display: none;
    }
}
::v-deep .BMapLib_bubble_top {
    border-bottom: none !important;
    height: auto;
    margin-bottom: 20px;
}
::v-deep .BMapLib_bubble_title {
    height: 22px;
    line-height: 22px;
    padding: 0;
    background: white !important;
    font-size: 16px !important;
    font-weight: 500 !important;
}
::v-deep .BMapLib_bubble_content {
    height: auto !important;
    padding: 0;
}
::v-deep .BMapLib_bubble_tools {
    background: white !important;
    margin-right: 10px !important;
    margin-top: 9px !important;
}
::v-deep .BMapLib_bubble_close {
    background-color: white !important;
}
</style>
